/*!
   \file

   \brief
      Windows implementation of timer.

   © 2011 Mark W. Gabby II

   This file is part of Rock Hunter.

   Rock Hunter is free software: you can redistribute it and/or modify it under the terms of the
   GNU General Public License as published by the Free Software Foundation, either version 3 of the
   License, or (at your option) any later version.

   Rock Hunter is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
   even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License along with Rock Hunter.
   If not, see <http://www.gnu.org/licenses/>.
*/

#include "Util/Timer.hpp"

#include <vector>

#define WIN32_LEAN_AND_MEAN
#define WINVER 0x501 // Windows XP
#include <windows.h>

#include "Systems/ErrorManager/ErrorManager.hpp"

static LARGE_INTEGER gCounterFrequency = { { 0 } };
std::vector<LARGE_INTEGER> gTimerIDsToStartCount;

/*!
    \brief
    Creates a Timer class with the specified countdown time.
*/
Timer::Timer( double Time )
{
   if ( gCounterFrequency.QuadPart == 0 )
   {
      QueryPerformanceFrequency( &gCounterFrequency );
   }

   timerTime = Time;
   id = gTimerIDsToStartCount.size();

   LARGE_INTEGER StartCounterCount;
   QueryPerformanceCounter( &StartCounterCount );
   gTimerIDsToStartCount.push_back( StartCounterCount );
}

/*!
    \brief
    Returns a number in seconds specifying how long it has been since the timer has expired.

    If the timer's time hasn't been reached yet, then it returns a negative number.
*/
double Timer::Check()
{
   const LARGE_INTEGER & StartCounterCount = gTimerIDsToStartCount[id];
   LARGE_INTEGER CurCounterCount;
   QueryPerformanceCounter( &CurCounterCount );

   double ElapsedSinceStart;
   ElapsedSinceStart = ( double )( CurCounterCount.QuadPart -
                                   StartCounterCount.QuadPart ) /
                       ( double )gCounterFrequency.QuadPart;

   return ElapsedSinceStart - timerTime;
}

/*!
    \brief
    This function resets the timer with it's last time.

    \return
    A number specifying how long it has been since the timer has expired.
    Negative if the timer hasn't exired yet.
*/
double Timer::Reset()
{
   double elapsedSinceTimeEnded = Check();

   // Reset the timer's start time.
   LARGE_INTEGER & StartCounterCount = gTimerIDsToStartCount[id];
   QueryPerformanceCounter( &StartCounterCount );

   return elapsedSinceTimeEnded;
}

/*!
    \brief
    This function sets the timer at a new time.
*/
void Timer::SetNewTime( double Time )
{
   timerTime = Time;

   Reset();
}

bool Timer::HasExpired()
{
   if ( Check() >= 0 )
   {
      return true;
   }

   return false;
}
